package ua.org.extjsbuilder.parser.runtime.builder;

import java.io.EOFException;
import java.util.LinkedList;
import java.util.List;

import ua.org.extjsbuilder.parser.IInstruction;
import ua.org.extjsbuilder.parser.runtime.UnparsedToken;
import ua.org.extjsbuilder.parser.runtime.instructions.Breaker;
import ua.org.extjsbuilder.parser.runtime.instructions.MemoryControl;
import ua.org.extjsbuilder.parser.runtime.instructions.With;
import ua.org.extjsbuilder.parser.scanner.CharPattern;

abstract class KeywordsInterpreter extends LValueInterpreter {

	KeywordsInterpreter(UnparsedToken start) {
		super(start);
	}
	
	@Override
	boolean next() throws EOFException {
		super.next();
		switch(state){
		case BREAK_STATEMENT:
			parseBreak();
			break;
		case CONTINUE_STATEMENT:
			parseContinue();
			break;
		case RETURN_STATEMENT:
			parseReturn();
			break;
		case NEW_STATEMENT:
			parseNew();
			break;
		case DELETE_STATEMENT:
			parseDelete();
			break;
		case WITH_STATEMENT:
			parseWith();
			break;
		}
		return true;
	}

	private void parseWith() throws EOFException {
		skipWhiteSpaces();
		if(data[pos]!='('){
			err("Open bracket expected");
		}
		IInstruction scope = new ExpressionsInterpreter(token,pos).buildExpression();
		skipWhiteSpaces();
		List<IInstruction> body;
		if(data[pos]=='{'){
			body = parseBlock(this);
		}
		else {
			body = new LinkedList<IInstruction>();
			GlobalInterpreter interpreter = new GlobalInterpreter(token,pos);
			while(interpreter.next()&&!interpreter.isComplete());
			body.add(interpreter.getLastComplete());
		}
		lastComplete = new With(scope,body);
		state = LEFT_START;
	}

	private void parseDelete() {
		IInstruction property = new ExpressionsInterpreter(token,pos).buildExpression();
		lastComplete = new MemoryControl(MemoryControl.NEW,property);
		state = LEFT_START;
	}

	private void parseNew() {
		IInstruction constructor = new ExpressionsInterpreter(token,pos).buildExpression();
		lastComplete = new MemoryControl(MemoryControl.NEW,constructor);
		state = LEFT_START;
	}

	private void parseReturn() throws EOFException {
		if(data.length>pos&&data[pos]!='('&&data[pos]!=';'&&
				!CharPattern.ALLOW_WHITE_SPACES.match(data[pos])){
			err("Syntax error");
		}
		skipWhiteSpaces();
		
		IInstruction expression = null;
		if(data[pos]!=';'){
			ExpressionsInterpreter exp = new ExpressionsInterpreter(token,pos);
			expression = exp.buildExpression();
			setState(exp);
			skipWhiteSpacesLine();
			if(data.length>pos&&data[pos]==';')pos++;
		}
		lastComplete = new Breaker(Breaker.RETURN,expression);
		state = LEFT_START;
	}

	private void parseContinue() throws EOFException {
		lastComplete = new Breaker(Breaker.CONTINUE,getLabel().toString());
		state = LEFT_START;
	}

	private void parseBreak() throws EOFException {
		lastComplete = new Breaker(Breaker.BREAK,getLabel().toString());
		state = LEFT_START;
	}

	private StringBuilder getLabel() throws EOFException {
		skipWhiteSpacesLine();
		StringBuilder label = new StringBuilder();
		if(pos<data.length&&data[pos]!=';'){
			while(pos<data.length&&
				JS_INDEFIER.match(data[pos])){
				label.append(data[pos++]);
			}
		}
		if(pos<data.length&&data[pos]!=';'){
			err("Syntax error");
		}
		if(pos<data.length&&data[pos]==';')pos++;
		return label;
	}
}
